<?php
error_reporting(0);
defined('_VALID_MOS') or die('Direct Access to this location is not allowed.');

$_MAMBOTS->registerFunction('onStart', 'JGFloodScan');
$_MAMBOTS->registerFunction('onAfterStart', 'JGInjectionScan');

$_MAMBOTS->registerFunction('onHeaders', 'JGFloodScan');
$_MAMBOTS->registerFunction('onHeaders', 'JGInjectionScan');

function JGFloodScan()
{

    
    $sql = "SELECT * FROM #__jguard_options Where id = 1";
    $options = getAssoc($sql);

    if (find_blocks_OnStart())
    {
        $ip = getenv("REMOTE_ADDR");
        $referer = parse_url(getenv("http_referer"));
        $email = '<a href="mailto:' . $mosConfig_mailfrom . '">' . $mosConfig_mailfrom .'</a>';

        include ('mambots/system/message_pages/block_page.php');
        exit;
    }
    if (FloodScan())
    {   
        $ip = getenv("REMOTE_ADDR");
        $type = 'Flood';
        $key = 'No Value';
        $val = 'No Value';      
        $email = '<a href="mailto:' . $mosConfig_mailfrom . '">' . $mosConfig_mailfrom .'</a>';
        include ('mambots/system/message_pages/stop_page.php');
        exit;
    }
}

function jdGetSkipWords($component, $val)
    {
      $out = array();
      if ($val)
      {

          $array = @explode("\n", str_replace("\r", '', $val));
          foreach ($array as $opt)
          {
              $tmp = explode("::", $opt);

              if ($tmp[0] == $component || $tmp[0]=='*')
              {
                  $out[] = trim(strtolower(@$tmp[1]));
              }
          }
      }

      return $out;
    }

  

function jdBlock($type, $options, $key = '', $val = '')
{
    global $mainframe, $database, $mosConfig_mailfrom;

    if ($type == 'SQL injection')
    {
        $ip = (boolean)eregi(2, $options[0][mysql_parameter]);
        $login = (boolean)eregi(3, $options[0][mysql_parameter]);
        $log = (boolean)eregi(0, $options[0][mysql_parameter]);
        $block = (boolean)eregi(1, $options[0][mysql_parameter]);
        $tomail = (boolean)($options[0][send_email] == 1 and $options[0][send_mysql_injection] == 1);

    }
    else
        if ($type == 'PHP injection')
        {
            $ip = (boolean)eregi(1, $options[0][file_parameter]);
            $login = (boolean)eregi(0, $options[0][file_parameter]);
            $block = true;
            $tomail = (boolean)($options[0][send_email] == 1 and $options[0][send_file_injection] == 1);
        }

    $referer = getenv("http_referer");
    $ip2 = getenv("REMOTE_ADDR");
    $email = '<a href="mailto:' . $mosConfig_mailfrom . '">' . $mosConfig_mailfrom .
        '</a>';

    
    $_GET[$key] = '<b>' . $val . '</b>';
    $get = serialize($_GET);
    $_POST[$key] = '<b>' . $val . '</b>';
    $post = serialize($_POST);
    $my = $mainframe->getUser();
    $user_id = $my->id;

    $sql = "SELECT `id` FROM #__jguard_log WHERE `ip` = '{$ip2}' AND `url` = '{$get}' AND post = '{$post}' AND `type` = '{$type}'";
    $database->setQuery($sql);
    $result = $database->loadResult();

     
     if ($tomail && !$result)
    {   
        send_mail("The attack of type {$type} was Discovered on your site.", $type);
    }
    if ($ip)
    {
        jdAddBlockList('ip', $ip2);
        include ('mambots/system/message_pages/stop_page.php');
        exit;
    }

    if ($log and !$block)
    {
        if (!$result)
        {
            jdefenderWriteLog($type, $block == true ? 'reject':'suspect');
        }
        else
        {
            $sql = "UPDATE #__jguard_log SET ctime = now() WHERE `id` = '{$result}'";
            $database->setQuery($sql);
            $database->query();
        }
    }

    if ($login)
    {
        jdAddBlockList('login', $user_id);
        include ('mambots/system/message_pages/stop_page.php');
        exit;
    }

    if ($block)
    {
        if (!$result)
        {
            jdefenderWriteLog($type, 'reject');
        }
        else
        {
            $sql = "UPDATE #__jguard_log SET ctime = now() WHERE `id` = '$result'";
            $database->setQuery($sql);
            $database->query();
        }
        include ('mambots/system/message_pages/stop_page.php');
        exit;
    }

   
}

function JGInjectionScan()
{
    global $database, $mainframe, $mosConfig_mailfrom, $mosConfig_live_site;

    $option = mosGetParam($_REQUEST, 'option');

    $email = '<a href="mailto:' . $mosConfig_mailfrom . '">' . $mosConfig_mailfrom .
        '</a>';
    $options = getAssoc("SELECT * FROM #__jguard_options");
    $gets = serialize($_GET);
    $url = $gets;


    if (find_blocks_OnAfterStart())
    {
        include ('mambots/system/jguard_message_page.php');
        exit;
    }

    #SEARCHING FOR SQL injectionS START *************************************************
    if ($options[0][mysql_scan] == 1)
    {
        $keywords = $options[0][mysql_keywords];
        $keywords = explode("\n", str_replace("\r", '', $keywords));
        $skipwords = jdGetSkipWords($option, $options[0]['sql_exeptions']);


	foreach ($_REQUEST as $key => $val)
        {
        if (@is_array($val))
          {
            foreach ($val as $v)
            {
              if (@in_array(strtolower($key), @$skipwords) || $val ==='' || @in_array("*", @$skipwords))
              {
                continue;
              }
              foreach ($keywords as $keyword)
              {
                if (@preg_match($keyword, $val))
                {
                  jdBlock('sql_injection', $key, $val);
                }
              }
            }
           }


          if (@in_array(strtolower($key), @$skipwords) || $val ==='' || @in_array("*", @$skipwords) )
          {
            continue;
          }

          // check ereg rules
          foreach ($keywords as $keyword)
          {
            if (@preg_match($keyword, $val))
            {
              jdBlock('sql_injection', $key, $val);
            }
          }
        }
    }


    //SEARCHING FOR  PHP INJECTIONS IN THE ADDRESS BAR

    if ($options[0][file_scan] == 1)
    {
        $file_rules = $options[0][file_keywords];
        $file_rules = explode("\n", str_replace("\r", "", $file_rules));
        $skipwords = jdGetSkipWords($option, $options[0]['php_exeptions']);
        $domain = preg_quote($mosConfig_live_site, "/");
       

	foreach ($_REQUEST as $key => $val)
        {
            
           if (@is_array($val))
            {
              foreach ($val as $v)
              {
                if (@in_array(strtolower($key), @$skipwords) || $val ==='' || @in_array("*", @$skipwords))
                {
                  continue;
                }
                foreach ($keywords as $keyword)
                {
                  if (@preg_match($keyword, $val))
                  {
                    jdBlock('php_injection', $key, $val);
                  }
                }
              }
             }  
	    if (@in_array(strtolower($key), @$skipwords))
            {
		 continue;
            }      
                                       
            if (preg_match("/^(http|https):\/\//", $val) and !preg_match("/" . $domain . "/", $request))
            {
                if (preg_match("/url|site|page|location|return/iU", $key) or $val=='')
                {
                  continue;
                }
                else 
                {
                  jdBlock('PHP injection', $options, $key, $val);
                }
            }
            // check ereg rules
            foreach ($file_rules as $keyword)
            {
                if (preg_match($keyword, $val))
                {   
                    jdBlock('PHP injection', $options, $key, $val);
                }
            }
        }
    }

    //SCANNIN THE FILES
    if (isset($_FILES))
    {
        foreach ($_FILES as $key => $val)
        { 
          if (trim($_FILES[$key]['tmp_name'])!='')
          {
              $fp = fopen($_FILES[$key]['tmp_name'], "r");
              $file_content = fread($fp, filesize($_FILES[$key]['tmp_name']));

              if (preg_match("/<\?(.+)\?>/iU", $file_content))
              {
                  jgBlock('PHP injection', $options);
              }
              fclose($fp);
          }
        }
    }
}

#SCANNING THE FILES END **********************************************************************
# MY SCRIPT ENDS HERE *************************************************************************
function send_mail($subject, $type)
{
    global $database, $mainframe, $mosConfig_mailfrom;
 
    $ip = getenv("REMOTE_ADDR");
    $referer = getenv("http_referer");
    $email = '<a href="mailto:' . $mosConfig_mailfrom . '">' . $mosConfig_mailfrom .
        '</a>';
    

    
    $text = "There was attack of type" . $type . " discovered on your site.\n";
    $text .= "\n";
    $text .= "Additional Information:\n";
    $text .= "---------------------------------------------\n";
    $text .= " TYPE:     $type\n";
    $text .= " IP:       $ip\n";
    if ($type != 'Flood'){
      $my = $mainframe->getUser();
      $text .= " USER:     [$my->id] $my->name\n";  
    } 
    
    $text .= " REFERER:  $referer\n";
    $text .= " GET:      " . print_r($_GET, true) . "\n";
    $text .= " POST:     " . print_r($_POST, true) . "\n";
    $text .= " COOCKIE:  " . print_r($_COOKIE, true) . "\n";
    //$text .= " SESSION:  ".print_r($_SESSION, true)."\n";
    $text .= "---------------------------------------------\n";
    $text .= "\n";
    $text .= "JDefender Joomla Bot\n";

    $options = getAssoc("SELECT * FROM #__jguard_options");
    mosMail($mosConfig_mailfrom, 'JDefender systembot', $options[0]["email"], $subject, $text, 0);
}

function find_blocks_OnAfterStart()
{
    global $database, $mainframe;
    $my = $mainframe->getUser();

    if (isset($my))
    {
        $user_id = $my->id;
    }
    else
    {
        $user_id = '';
    }
    $UserIp = getenv("REMOTE_ADDR");

    $query = "select count(`type`) from #__jguard_block_list where ";
    $query .= " `type` = 'login' and `value` = '" . $user_id . "' ";

    $database->setQuery($query);
    $user_data = getObjectList($query);
    $count_blocks = $database->loadResult();

    if ($count_blocks > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}


function find_blocks_OnStart()
{
    global $database;

    $UserIp = getenv("REMOTE_ADDR");

    $query = "select count(`type`) from #__jguard_block_list where ";
    $query .= " (`type` = 'ip' and `value` = '" . $UserIp . "') ";
    $gets = "";
    reset($_GET);
    $count = 0;
    while (list($key, $val) = each($_GET))
    {
        if (in_array($key, array('')) == '')
        {
            $count++;
            if ($count > 1)
            {
                $gets .= " or ";
            }
            $gets .= "`value`='" . $key . "=" . $val . "'";
        }
    }
    if ($gets)
    {
        $query .= " or (`type` = 'get' and (" . $gets . ")) ";
    }
    $posts = "";
    reset($_POST);
    $count = 0;
    while (list($key, $val) = each($_POST))
    {
        if (in_array($key, array('')) == '')
        {
            $count++;
            if ($count > 1)
            {
                $posts .= " or ";
            }
            $posts .= "`value`='" . $key . "=" . $val . "'";
        }
    }
    if ($posts)
    {
        $query .= " or (`type` = 'post' and (" . $posts . ")) ";
    }
    //$query.=" or (`type` = 'login' and `value` = '".$user_id."') ";
    
    $referer = parse_url(getenv("http_referer"));
    if (empty ($referer['host'])) $referer['host']='';
    $query .= " or (`type` = 'referer' and `value` = '" . $referer['host'] . "') ";

    $database->setQuery($query);
    $user_data = getObjectList($query);
    $count_blocks = $database->loadResult();

    if ($count_blocks > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}
function FloodScan()
{
    
    global $database, $mosConfig_mailfrom;
   
    $flood = false;
    
    $description = '';
    $options = getAssoc("select * from #__jguard_options");

    $UserIp = getenv("REMOTE_ADDR");

    $database->setQuery("DELETE FROM `#__jguard_flood_monitor` WHERE `time` < (now() - INTERVAL 1 DAY)");
    $database->query();

    if ($options[0]["untiflood"] == 1)
    {
        $database->setQuery("INSERT INTO #__jguard_flood_monitor (`ip`,`time`) " .
            "VALUES ('{$UserIp}', NOW())");
        $database->query();
       
        for ($i = 1; $i <= 3; $i++)
        {
            switch ($i)
            {
                case 1:
                    $timeofset = " SECOND";
                    break;
                case 2:
                    $timeofset = " MINUT";
                    break;
                case 3:
                    $timeofset = " HOUR";
                    break;
            }
            
            if (($options[0]["flood_queries_" . $i] > 0) && ($options[0]["flood_time_" . $i] > 0))
            {
                $database->setQuery("SELECT COUNT(`ip`) FROM #__jguard_flood_monitor WHERE `ip` " .
                    "= '{$UserIp}' AND `time` >= NOW() - INTERVAL " . $options[0]["flood_time_" . $i] .
                    " $timeofset");
                $count_queries = $database->loadResult();
                if ($count_queries >= $options[0]["flood_queries_" . $i])
                {
                    
                    if (eregi(1, $options[0][flood_parameter]))
                    {
                        jdAddBlockList("ip", $UserIp);
                    }
                     
                    $flood = true;
                    
                }
            }
        }

        if ($flood == true)
        {
          
            if (eregi(1, $options[0][flood_parameter]))
            {
                $descripton = "Blocked on commecing the attack of type flood(the rule: not more " .
                    $options[0]["flood_queries_" . $i] . " queries in " . $options[0]["flood_time_" .
                    $i] . " seconds)";
                    
            }
            else
            {
                $descripton = "Rejected on commecing the attack of type flood(the rule: not more " .
                    $options[0]["flood_queries_" . $i] . " queries in " . $options[0]["flood_time_" .
                    $i] . " seconds)";
            }
            //$UserIp = getenv("REMOTE_ADDR");
            $database->setQuery("SELECT * FROM #__jguard_log WHERE `ip` = '{$UserIp}' and type = 'Flood'");
            $res = $database->loadResult();
             
            if ($res)
            {
                $database->setQuery("UPDATE #__jguard_log SET `ctime` = now() WHERE `ip` = '{$UserIp}' AND `type` = 'Flood'");
                $database->query();
               
            }
            else
            {
              jdefenderWriteLog('Flood', 'reject');             
            }
            if ($options[0][send_email] == 1 and $options[0][send_flood] == 1)
            {
               
                @send_mail("The attack of type Flood was Discovered on your site.", 'Flood');
                
            }
        }
    }
      
    return $flood;
}

/*function injection_jdAddBlockList()
{
global $database, $mainframe;
$database->setQuery("select * from #__jguard_options");
$options=$database->loadAssocList();

$my = $mainframe->getUser();
if(isset($my))	{ $user_id=$my->id; }
else { $user_id=''; }
$UserIp=getenv ("REMOTE_ADDR");
$referer=parse_url(getenv ("http_referer"));
if($options[0]["block_injections"]==1)
{
if($options[0]["block_ip"]==1)		{jdAddBlockList("ip",$UserIp);}
if($options[0]["block_login"]==1)	{jdAddBlockList("login",$user_id);}
if($options[0]["block_referer"]==1)	{jdAddBlockList("referer",$referer["host"]);}
}
}*/
function jdAddBlockList($type, $value)
{

    global $database;
    if ($value)
    {
        $database->setQuery("select count(type) from #__jguard_block_list where `type`='" .
            $type . "' and `value`= '" . $value . "'");
        $count_rows = $database->loadResult();
        if ($count_rows == 0)
        {
            $database->setQuery("insert into #__jguard_block_list (`type`, `value`) values ('" .
                $type . "','" . $value . "')");
            $database->query();
        }
    }
}

function jdefenderWriteLog($type, $log)
{
    global $database, $mainframe, $my;

    if ($type!='Flood'){
    $my = $mainframe->getUser();
    $user_id = $my->id;
    }
    $UserIp = getenv("REMOTE_ADDR");
    $get = serialize($_GET);
    $post = serialize($_POST);
    $ref = getenv("http_referer");

    $database->setQuery("insert into #__jguard_log (`ip`, `ctime`, `type`, `user_id`," .
        " `url`, `post`, `cook`, `referer`, `description`,`suspect_reject`) " .
        "values ('{$UserIp}', now(),'{$type}','{$user_id}','{$get}','{$post}', " .
        "'', '{$ref}', '', '{$log}')");
    $database->query();
}

function getAssoc($sql)
{
    global $mosConfig_MetaKeys, $database, $_VERSION;
    if ($_VERSION->PRODUCT == 'Joomla!')
    {//for Joomla
        $database->setQuery($sql);
        $result = $database->loadAssocList();
        return $result;
    }
    else
        if ($_VERSION->PRODUCT == 'Mambo')
        {//for Mambo
            $database->setQuery($sql);
            $result = $database->retrieveResults('', 0, 'assoc');
            return $result;
        }
}

function getObjectList($sql)
{
    global $database, $mosConfig_MetaKeys, $_VERSION;
    if ($_VERSION->PRODUCT == 'Joomla!')
    {//for Joomla
        $database->setQuery($sql);
        $result = $database->loadObjectList();
        return $result;
    }
    else
        if ($_VERSION->PRODUCT == 'Mambo')
        {//for Mambo
            $database->setQuery($sql);
            $result = $database->retrieveResults('', 0, 'object');
            return $result;
        }
}
?>